package org.fuys.coder.infrastructure.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.fuys.coder.infrastructure.model.dto.UserModelDTO;
import org.fuys.coder.common.entity.Pair;
import org.fuys.coder.domain.model.repository.IUserModelRepository;
import org.fuys.coder.infrastructure.dao.UserModelMapper;
import org.fuys.coder.infrastructure.model.po.UserModel;
import org.fuys.coder.infrastructure.util.RedisUtil;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @projectName: fuys-low-coder
 * @package: org.fuys.coder.infrastructure.repository
 * @className: UserModelRepositoryImpl
 * @author: WangJing
 * @description: 用户模型仓储实现
 * @date: 2024/6/26 16:59
 * @version: 1.0
 */
@Service
public class UserModelRepositoryImpl extends ServiceImpl<UserModelMapper, UserModel>
        implements IUserModelRepository {

    @Resource
    private UserModelMapper userModelMapper;

    @Resource
    private RedisUtil redisUtil;

    @Override
    public List<UserModelDTO> getRoughModel(Integer userId) {
        //这里只管查 如果存在一些数据已经严重过时 当用户离开页面时会发送请求 然后交给对应的数据更新事件监听处理
        final List<UserModel> userModels = userModelMapper.selectList(new LambdaQueryWrapper<UserModel>()
                .select(UserModel::getCategoryId,UserModel::getCategoryWeight).eq(UserModel::getUserId, userId));
        if(ObjectUtils.isEmpty(userModels)){
            //如果数据库中都没有数据 就继续Plan B 进行随机推荐 这里直接返回null处理
            return null;
        }
        return userModels.stream().map(
                userModel -> {
                    UserModelDTO userModelDTO = new UserModelDTO();
                    userModelDTO.setCategoryId(userModel.getCategoryId());
                    userModelDTO.setCategoryWeight(userModel.getCategoryWeight());
                    return userModelDTO;
                }
        ).collect(Collectors.toList());
    }

    @Override
    public void saveUserModel(Integer userId,List<Pair<Integer, Double>> collect) {
        if(ObjectUtils.isEmpty(collect)){
            return;
        }
        final List<UserModel> dbResult = collect.stream().map(item -> {
            UserModel userModel = new UserModel();
            userModel.setUserId(userId);
            userModel.setCategoryId(item.getLeft());
            userModel.setCategoryWeight(item.getRight());
            return userModel;
        }).collect(Collectors.toList());
        userModelMapper.batchIgnoreErrorSave(dbResult);
    }

    @Override
    public Set<ZSetOperations.TypedTuple<Object>> getExpiredModel(String redisKey, int i) {
        return redisUtil.zsetGetMembersAndScore(redisKey,-1);
    }

    @Override
    public void addModelExpired(String redisUserModelKey, Integer userId, double time) {
        redisUtil.zsetAdd(redisUserModelKey,userId,time);
    }

    @Override
    public void addCacheUserWeights(String redisKey, Pair<Integer, Double> integerDoublePair) {
        redisUtil.addList(redisKey,integerDoublePair);
    }

    @Override
    public void cacheUserWeights(String redisKey, List<Pair<Integer, Double>> collect) {
        redisUtil.setList(redisKey,collect);
    }

    @Override
    public List<Object> getCacheWeightPair(String redisKey) {
        return redisUtil.getList(redisKey);
    }
}
